// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package runtime

import "unsafe"

type sigctxt struct {
	info *siginfo
	ctxt unsafe.Pointer
}

// go:nosplit 
// go:NOWRITEBRIERREC 
func (c *sigctxt) regs() *regs64 { return &(*ucontext)(c.ctxt).uc_mcontext.ss }

func (c *sigctxt) rax() uint64 { return c.regs().rax }
func (c *sigctxt) rbx() uint64 { return c.regs().rbx }
func (c *sigctxt) rcx() uint64 { return c.regs().rcx }
func (c *sigctxt) rdx() uint64 { return c.regs().rdx }
func (c *sigctxt) rdi() uint64 { return c.regs().rdi }
func (c *sigctxt) rsi() uint64 { return c.regs().rsi }
func (c *sigctxt) rbp() uint64 { return c.regs().rbp }
func (c *sigctxt) rsp() uint64 { return c.regs().rsp }
func (c *sigctxt) r8() uint64  { return c.regs().r8 }
func (c *sigctxt) r9() uint64  { return c.regs().r9 }
func (c *sigctxt) r10() uint64 { return c.regs().r10 }
func (c *sigctxt) r11() uint64 { return c.regs().r11 }
func (c *sigctxt) r12() uint64 { return c.regs().r12 }
func (c *sigctxt) r13() uint64 { return c.regs().r13 }
func (c *sigctxt) r14() uint64 { return c.regs().r14 }
func (c *sigctxt) r15() uint64 { return c.regs().r15 }

// go:nosplit 
// go:NOWRITEBRIERREC 
func (c *sigctxt) rip() uint64 { return c.regs().rip }

func (c *sigctxt) rflags() uint64  { return c.regs().rflags }
func (c *sigctxt) cs() uint64      { return c.regs().cs }
func (c *sigctxt) fs() uint64      { return c.regs().fs }
func (c *sigctxt) gs() uint64      { return c.regs().gs }
func (c *sigctxt) sigcode() uint64 { return uint64(c.info.si_code) }
func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }

func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
func (c *sigctxt) set_sigaddr(x uint64) { c.info.si_addr = x }

// go nosplit 
func (c *sigctxt) fixsigcode(sig uint32) {
	switch sig {
	case _SIGTRAP:
		// OS X设置c.sigcode（）=TRAP_BRKPT无条件地用于所有SIGTRAP，
		// 无法区分断点诱导的SIGTRAP 
		// 。
		// 它们看起来都是默认的断点。
		// 尝试查看代码，看看它是否是断点。
		// 假设我们不太可能在
		// 异步信号陷阱。
		// PC开始指向未映射内存的那一刻得到一个
		pc := uintptr(c.rip())
		// OS X将在INT 3指令发出后立即离开电脑。
		// INT 3通常是1字节，但有2字节的形式。
		code := (*[2]byte)(unsafe.Pointer(pc - 2))
		if code[1] != 0xCC && (code[0] != 0xCD || code[1] != 3) {
			// INT 3以外的其他内容上的SIGTRAP。
			c.set_sigcode(_SI_USER)
		}

	case _SIGSEGV:
		// x86-64有48位虚拟地址。前16位必须与第47位相呼应。
		// 与试图访问有效但未映射的地址相比，硬件为格式错误的地址提供了不同类型的故障。
		// OS X 10.9.2错误处理了格式错误的地址大小写，使其看起来像
		// /一个用户生成的信号（就像有人运行kill-SEGV ourpid）。
		// 我们将用户生成的信号传递给os/signal，或者忽略它们。
		// 在这里这样做——并返回错误代码——会导致一个
		// 无限循环。看来我们能做的最好的事情就是重写内核
		// 提供的内容，使其更接近事实。下面使用的地址几乎不可能是导致故障的地址，但它的格式不正确，显然不是真正的指针，如果在现实生活中打印出来，人们可能会搜索它并找到此代码。
		// 当我键入此评论时，没有针对b01dfacedebac1e或0xb01dfacedebac1e的谷歌点击量。
		if c.sigcode() == _SI_USER {
			c.set_sigcode(_SI_USER + 1)
			c.set_sigaddr(0xb01dfacedebac1e)
		}
	}
}
